home *** CD-ROM | disk | FTP | other *** search
-
- /* glue funs and things that substitute for eunuchs funs */
-
- #include <stdio.h>
- #include <osbind.h>
- #include <setjmp.h>
- #include <ctype.h>
- #include <signal.h>
- #include <regexp.h>
- #include "st-traps.h"
- #include "wait.h"
- #include "m-atari.h"
- #include "defs.h"
- #include "symtab.h"
-
- struct tpa /* what the hell does 'tpa' stand for anyway?*/
- {
- struct tpa * self; /* self or parent??? */
- long * memtop; /* top of mem this tpa */
- long * text_base;
- long text_size;
- long * data_base;
- long data_size;
- long * bss_base;
- long bss_size;
- /* there's more crap here, but I think it doesn't matter */
- };
-
- struct tpa * child_tpa;
- int atari_debug = 0;
-
- #if 0
- long _stksize = 128 *1024L; /* might as well put this here */
- #else
- long _initial_stack = 512 *1024L;
- #endif
-
- #define CHILD_PID_KLUDGE 1
-
- int child_is_running = 0;
-
- long old_vectors[10];
- long old_trap_0_vector;
- long old_trap_f_vector;
-
- long set_exception_vector();
-
- #if 1 /* def JRDLIB */
- /* for st-infru.c */
- char * sys_siglist[] =
- {
- "null",
- "alarm",
- "bus error",
- "address error",
- "illegal instruction",
- "div by zero",
- "CHK instruction",
- "TRAPV instruction",
- "priv violation",
- "T-bit trap",
- "Breakpoint",
- "interrupt",
- "quit"
- };
- #endif
-
- /* for st-inflo.c... */
- static volatile jmp_buf exec_context, pre_pexec_context;
-
- static char kludge_cmd[MAXPATHLEN];
- static char * kludge_argstring;
- static char * kludge_env;
- static volatile long kludge_pexec_result;
-
- static char pexec_stack[256];
-
- st_execle_kludge(args, env)
- /* BOGON ALERT!!! the caller has 'args' declared as a char **, but
- that's clearly bogus, given the way it's constructed. Look in
- infcmd.c. It's really a char *. I hate C... */
- char * args;
- char ** env;
- {
- int i, envlen;
- char cmdname[80], argstring[258];
- char * p, * q;
- static char run_already = 0;
-
- if(run_already)
- return -9999;
- else
- run_already = 1;
-
- /* zzz */
- /*
- fprintf_filtered(stderr, "Execle_kludge:\n");
- fprintf_filtered(stderr, "\t'%s'\n", args);
-
- fprintf_filtered(stderr, "\tenv:\n");
- for (i = 0 ; env[i] ; i++)
- fprintf_filtered(stderr, "\t\t'%s'\n", env[i]);
- */
-
- /* construct the environment string */
- envlen = 0;
- for (i = 0; env[i]; i++)
- envlen += strlen(env[i]) + 1;
- envlen += 1;
-
- p = kludge_env = xmalloc(envlen);
-
- for (i = 0; env[i]; i++)
- {
- /*
- * NOTE: in main.c, we converted the PATH environment variable into
- * POSIX form. Here, we convert back into gulam form. Note that the
- * new variable will be shorter than the old, so space is not a
- * problem.
- */
- if (!strncmp (env[i], "PATH=", 5))
- {
- strncpy (p, env[i], 5);
- p += 5;
- for (q = env[i] + 5; *q; q++)
- {
- if (!strncmp (q, "/dev/", 5) && q[5])
- {
- *p++ = q[5];
- *p++ = ':';
- q += 5;
- }
- else if (*q == ':')
- *p++ = ',';
- else if (*q == '/')
- *p++ = '\\';
- else
- *p++ = *q;
- }
- }
- else
- for (q = env[i]; *q; q++)
- *p++ = *q;
- *p++ = '\0';
- }
- *p = '\0';
-
- /* the obligatory cmd line parsing */
- cmdname[0] = '\0';
- /* cmd string has 'exec' in front of it. */
- for (p = args + 4 ; (*p && isspace(*p)) ; p++)
- ;
- for (q = &cmdname[0] ; (*p && !isspace(*p)) ; )
- *q++ = *p++;
- *q = '\0';
- for ( ; (*p && isspace(*p)) ; p++)
- ;
- argstring[1] = '\0';
- for (q = &argstring[1] ; (*p) ; )
- *q++ = *p++;
- *q = '\0';
- argstring[0] = strlen(&argstring[1]);
- unx2dos(&cmdname[0], kludge_cmd);
-
- exception_number = 0;
- old_ipl_2_vector =
- set_exception_vector(26, ipl_2_vector); /* our startup trap */
- if (!setjmp(exec_context))
- {
- /* ok, we're either coming thru here the first time, before
- the spawn, or after taking the kludge return. child_running
- tells us which one */
- if (child_is_running)
- {
- /* something's really fucked here. We're not supposed to
- be able to come thru here except when we're starting
- things */
- fprintf_filtered(stderr, "Internal error!!! child already running?\n");
- return(0);
- }
- else
- {
- /* set the running flag, arrange to return to that setjmp above,
- and start the child. */
- child_is_running = 1;
- setup_fake_debugger_context(exec_context);
-
- /* if we could be sure of the stack, we'd say...
- Pexec(PE_LOADGO, cmdname, argstring, env);
- but we can't. instead... */
-
- /* fprintf_filtered(stderr, "Pexec('%s', '%s')\n",
- &cmdname[0], &argstring[1]);
- */
- /* kludge_cmd = &cmdname[0]; */
- kludge_argstring = &argstring[0];
-
- if(setjmp(pre_pexec_context))
- {
- free(kludge_env);
- /* we're returning after the child exits. the stack
- is all fucked here, so reset to top level */
- child_is_running = 0;
- fprintf(stderr, "Program exitted with status %ld\n",
- kludge_pexec_result);
- exception_number = SIGTRACE; /* not really... */
- inferior_died(); /* I think this is safe here */
- return_to_top_level(); /* clean up stack and restart */
- return(CHILD_PID_KLUDGE); /* just in case ... */
-
- }
- /* must make sp point to someplace nonvolatile, as we're going to do
- a bunch of context switching before we actually 'exit' from this
- pexec. */
- #ifndef OLDTOS
- /* default - TOS 1.4 or better required
- use Pexec 3+6 */
-
- asm volatile("\
- movel #_pexec_stack+252,sp
- movel _kludge_env,sp@-
- movel _kludge_argstring,sp@-
- movel #_kludge_cmd,sp@-
- movew #3,sp@-
- movew #0x4B,sp@-
- trap #1
- addw #16,sp
- clrl sp@-
- movel d0, sp@-
- clrl sp@-
- movew #6, sp@-
- movew #0x4B,sp@-
- trap #1
- movel d0,_kludge_pexec_result");
- #else
- /* pre tos 1.4 -- get a life man
- use Pexec 0 */
- asm volatile("\
- movel #_pexec_stack+252,sp
- movel _kludge_env,sp@-
- movel _kludge_argstring,sp@-
- movel #_kludge_cmd,sp@-
- movew #0,sp@-
- movew #0x4B,sp@-
- trap #1
- movel d0,_kludge_pexec_result");
- #endif
-
- #if 0
- free(kludge_env);
- /* we're returning after the child exits. the stack
- is all fucked here, so reset to top level */
- child_is_running = 0;
- exception_number = SIGTRACE; /* not really... */
- inferior_died(); /* I think this is safe here */
- return_to_top_level(); /* clean up stack and restart */
- #else
- longjmp(pre_pexec_context, 1);
- #endif
- }
- }
- else
- {
- /* we have just spawned the child, and are returning from
- preparing to execute him. return
- the fake pid so we can continue initialiation */
- set_exception_vector(26, old_ipl_2_vector);
- {
- long * child_sp = (long *)child_context.registers[15];
- child_tpa = (struct tpa * )child_sp[1];
- /* fprintf_filtered(stderr, "child tpa at %X\n", child_tpa); */
- relocate_apropriate_symbols(child_tpa->text_base);
- exception_number = 0;
- }
- }
- return(CHILD_PID_KLUDGE);
- }
-
- #if 1 /* def JRDLIB */
- /* called various places */
- int kill(fake_pid, signal)
- int fake_pid;
- int signal;
- {
- extern void request_quit();
-
- if (fake_pid == CHILD_PID_KLUDGE)
- {
- /* if the child is running, then TOS thinks we're it, so just exit */
- if (child_is_running)
- Pterm0();
- /* doesn't return... */
- else
- fprintf_filtered(stderr, "Internal error: attempt to kill when child not running\n");
- }
- else if (fake_pid == getpid ())
- {
- if (signal == SIGINT)
- request_quit();
- }
- else
- fprintf_filtered(stderr, "You can't kill pid %d, bozo!\n", fake_pid);
-
- return(-1);
- }
- #endif
-
- /* called from various places, mostly st-infru.c */
- int st_wait_kludge(w)
- WAITTYPE * w;
- {
- /* fprintf_filtered(stderr, "st-wait-kludge: running %d exc %d\n",
- child_is_running, exception_number); */
- if (child_is_running)
- {
- WSETSTOP(*w, exception_number);
- return(CHILD_PID_KLUDGE);
- }
- else
- {
- WSETEXIT(*w, 0);
- return(-1);
- }
- }
-
-
- static char *regcomp_error = 0;
- static regexp *compiled_regex = 0;
-
- /* Remember the last error message from regcomp */
- void regerror(message)
- char *message;
- {
- regcomp_error = message;
- }
-
- char *re_comp(regex)
- char *regex;
- {
- regcomp_error = NULL;
- if (compiled_regex) free(compiled_regex);
- if (compiled_regex = regcomp(regex))
- return NULL;
- else
- return regcomp_error;
- }
-
- int re_exec(buffer)
- char *buffer;
- {
- if (compiled_regex)
- return regexec(compiled_regex, buffer, 1);
- else
- return -1;
- }
-
- /* low-level exception-handling support */
-
- long set_exception_vector(n, entry_point)
- /* (declare (values old-vector)) */
- int n;
- long entry_point; /* really a function... */
- {
- long old_vector;
- /* fprintf_filtered(stderr, "set exception %d %X", n, entry_point); */
- old_vector = (long)Setexc(n, entry_point); /* better way? */
- /* fprintf_filtered(stderr, " -> %X\n", old_vector); */
- return(old_vector);
- }
-
- set_all_exception_vectors()
- {
- old_vectors[2] = set_exception_vector(2, exception_2_vector);
- old_vectors[3] = set_exception_vector(3, exception_3_vector);
- old_vectors[4] = set_exception_vector(4, exception_4_vector);
- old_vectors[5] = set_exception_vector(5, exception_5_vector);
- old_vectors[6] = set_exception_vector(6, exception_6_vector);
- old_vectors[7] = set_exception_vector(7, exception_7_vector);
- old_vectors[8] = set_exception_vector(8, exception_8_vector);
- old_vectors[9] = set_exception_vector(9, exception_9_vector);
-
- old_trap_0_vector = set_exception_vector(32, trap_0_vector);
- old_trap_f_vector = set_exception_vector(47, trap_f_vector);
- /* we don't set the ipl 2 vector here as we'll only use it once,
- when starting */
- }
-
- restore_all_exception_vectors()
- {
- set_exception_vector(2, old_vectors[2]);
- set_exception_vector(3, old_vectors[3]);
- set_exception_vector(4, old_vectors[4]);
- set_exception_vector(5, old_vectors[5]);
- set_exception_vector(6, old_vectors[6]);
- set_exception_vector(7, old_vectors[7]);
- set_exception_vector(8, old_vectors[8]);
- set_exception_vector(9, old_vectors[9]);
-
- set_exception_vector(32, old_trap_0_vector);
- set_exception_vector(47, old_trap_f_vector);
- }
-
- /* -- here's a bunch of stuff for controlling the 'child' program */
-
- /* force the child process to exit */
- st_child_exit()
- {
- /* fprintf_filtered(stderr, "st_child_exit\n"); */
- if (child_is_running)
- Pterm0();
- else
- fprintf_filtered(stderr, "Internal error: child not running?\n");
- }
-
- /* continue after bpt */
- st_child_continue()
- {
- /* fprintf_filtered(stderr, "st_child_continue\n"); */
- if (child_is_running)
- {
- set_all_exception_vectors(); /* set our traps */
- child_context.sr &= 0x7FFF; /* clear T bit */
- asm volatile("trap #0"); /* swap context */
- /* child runs here, and returns to us */
- restore_all_exception_vectors(); /* and put our traps back */
- }
- else
- fprintf_filtered(stderr, "Internal error: child not running?\n");
- }
-
- /* single step */
- st_child_single_step()
- {
- /* fprintf_filtered(stderr, "st_child_single_step\n"); */
- if (child_is_running)
- {
- set_all_exception_vectors(); /* set our traps */
- child_context.sr |= 0x8000; /* set T bit */
- asm volatile("trap #0"); /* swap context */
- restore_all_exception_vectors(); /* and put our traps back */
- }
- else
- fprintf_filtered(stderr, "Internal error: child not running?\n");
- }
-
- /* read a register from saved copies */
- long st_child_read_register(regaddr)
- int regaddr;
- {
- long result;
-
- /* fprintf_filtered(stderr, "st_child_read_register %X ", regaddr); */
- if (child_is_running)
- {
- if ((regaddr >> 2) == PS_REGNUM)
- result = child_context.sr;
- else
- {
- result = ( *(long * )(regaddr + (char * )&child_context));
- /*
- if ((exception_number == 2) || (exception_number == 3))
- {
- fprintf_filtered(stderr, "Adjusting pc for trap %d %08X->%08X\n",
- exception_number, result, result+8);
- result += 8;
- }
- */
- }
- /* fprintf_filtered(stderr, "-> %X\n", result); */
- }
- else
- fprintf_filtered(stderr, "Child is not running\n");
- return(result);
- }
-
- /* write a register to saved copies */
- st_child_write_register(regaddr, value)
- int regaddr, value;
- {
- /* fprintf_filtered(stderr, "st_child_write_register %X <- %X\n", regaddr, value); */
- if (child_is_running)
- {
- if ((regaddr >> 2) == PS_REGNUM)
- child_context.sr = value;
- else
- *(long * )(regaddr + (char * )(&child_context)) = value;
- }
- else
- fprintf_filtered(stderr, "Child is not running\n");
- }
-
- void st_bus_error_handler ()
- {
- asm volatile ("andw #~0x2000,sr");
- error ("Bus error while reading from or writing to child memory.");
- }
-
- /* read a 32-bit word from child memory */
- st_child_read_word(addr)
- volatile long * addr;
- {
- long result;
- long old_buserror;
-
- /* fprintf(stderr, "st_child_read_word %X", addr); */
- /* report bus errors */
- old_buserror = (long) Setexc (2, st_bus_error_handler);
- result = *addr;
- (void) Setexc (2, old_buserror);
- /* fprintf(stderr, "->%X\n", result); */
- return(result);
- }
-
- /* write a 32-bit word to child mem */
- st_child_write_word(addr, value)
- long * addr;
- volatile long value;
- {
- long old_buserror;
- /* fprintf(stderr, "st_child_write_word %X <- %X\n", addr, value); */
- /* report bus errors */
- old_buserror = (long) Setexc (2, st_bus_error_handler);
- *addr = value;
- (void) Setexc (2, old_buserror);
- }
-
- #define DEBUG 1
-
- #ifdef DEBUG
- static char *d_namespace[] =
- { "UNDEF", "VAR", "STRUCT", "LABEL" };
-
- static char *d_aclass[] =
- {
- "LOC_UNDEF", "LOC_CONST", "LOC_STATIC", "LOC_REGISTER", "LOC_ARG", "LOC_LOCAL",
- "LOC_TYPEDEF", "LOC_LABEL", "LOC_BLOCK", "LOC_EXTERNAL", "LOC_CONST_BYTES"
- };
-
- #endif
-
- /********************************************************************
-
- This next thing is the symbol-table relocator. We use it after
- starting a child program.
-
- Walk thru all symbol tables looking for syms in VAR_NAMESPACE.
- When find one, if its address_class is LOC_STATIC, relocate its
- value by base_address. Then cross fingers and pray...
-
- */
- relocate_apropriate_symbols(base_address)
- long base_address;
- {
- struct symtab * s;
- struct symbol * sym;
- struct blockvector * bv, *last_bv = 0;
- struct block * block;
- struct linetable * l;
- int nsyms, symnum, i;
- extern char *version;
-
- #ifdef DEBUG
- if(atari_debug)
- {
- fprintf_filtered(stderr,"Reloc constant %ld %X\n", base_address, base_address);
- }
- #endif
- for (s = symtab_list ; s ; s = s->next)
- {
- l = LINETABLE(s);
- #ifdef DEBUG
- if(atari_debug)
- {
- fprintf_filtered(stderr,
- "reloc syms table %X file '%s' linetable %08X(%ld) %d items\n",
- s, s->filename, l,l, l->nitems);
- }
- #endif
- {
- int n = l->nitems;
- struct linetable_entry *item;
-
- #ifdef DEBUG
- if(atari_debug && (n <= 0))
- {
- fprintf_filtered(stderr,"*********linetable with %d items\n", n);
- }
- #endif
- for (i = 0 ; i < n ; i++)
- {
- item = &(l->item[i]);
- #ifdef DEBUG
- if(atari_debug)
- {
- fprintf_filtered(stderr, " %d: line %d %X(%ld)->%X(%ld)\n",
- i, item->line, item->pc, item->pc,
- item->pc+base_address, item->pc+base_address);
- }
- #endif
- item->pc += base_address;
- }
- }
- bv = BLOCKVECTOR (s);
- if (bv == last_bv)
- {
- /* already relocated */
- #ifdef DEBUG
- if(atari_debug)
- {
- fprintf_filtered(stderr,"Skipping block vector %X(%d) already relocated\n", bv,bv);
- }
- #endif
- continue;
- }
- last_bv = bv;
- for (i = 0 ; i < BLOCKVECTOR_NBLOCKS(bv) ; i++)
- {
- block = BLOCKVECTOR_BLOCK (bv, i);
- #ifdef DEBUG
- if(atari_debug)
- {
- fprintf_filtered(stderr, " block %d: in %X(%d)\n", i, bv, bv);
- }
- #endif
- relocate_apropriate_block_symbols(block, base_address);
- }
- }
- #ifdef DEBUG
- if(atari_debug)
- {
- fprintf_filtered(stderr,"Relocatings %d misc functions\n", misc_function_count);
- }
- #endif
- /* relocate the misc functions */
- for (i = 0; i < misc_function_count; i++)
- {
- #ifdef DEBUG
- if(atari_debug > 1)
- {
- fprintf_filtered(stderr, "%s: %X(%ld)->%X(%ld)\n", misc_function_vector[i].name,
- misc_function_vector[i].address, misc_function_vector[i].address,
- misc_function_vector[i].address+base_address, misc_function_vector[i].address+base_address);
- }
- #endif
- misc_function_vector[i].address += base_address;
- }
-
- }
-
- relocate_apropriate_block_symbols(block, base_address)
- struct block * block;
- long base_address;
- {
- struct symbol * sym;
- int nsyms, symnum;
-
- /* for ( ; block ; block = BLOCK_SUPERBLOCK(block)) */
- {
- BLOCK_START(block) += base_address;
- BLOCK_END(block) += base_address;
- nsyms = BLOCK_NSYMS (block);
- #ifdef DEBUG
- if(atari_debug)
- {
- fprintf_filtered(stderr, " %d syms block %X(%ld)\n", nsyms, block, block);
- }
- #endif
- for (symnum = 0 ; symnum < nsyms ; symnum++)
- {
- sym = BLOCK_SYM (block, symnum);
- #ifdef DEBUG
- if(atari_debug)
- {
- fprintf_filtered(stderr, " sym %d %X name '%s'",
- symnum, sym, SYMBOL_NAME(sym));
- }
- #endif
- if ((sym->namespace == VAR_NAMESPACE) &&
- ((sym->class == LOC_STATIC) || (sym->class == LOC_LABEL)))
- {
- #ifdef DEBUG
- if(atari_debug)
- {
- fprintf_filtered(stderr, " is relocatable: (%s, %s) %X->%X %ld->%ld\n",
- d_namespace[sym->namespace], d_aclass[sym->class],
- sym->value.value, sym->value.value + base_address,
- sym->value.value, sym->value.value + base_address);
- }
- #endif
- sym->value.value += base_address;
- }
- else if (sym->class == LOC_BLOCK)
- {
- #ifdef DEBUG
- if(atari_debug)
- {
- fprintf_filtered(stderr, " is a LOC_block(%s %s)... %X\n",
- d_namespace[sym->namespace], d_aclass[sym->class], sym->value.block);
- }
- #endif
- #if 0
- relocate_apropriate_block_symbols(sym->value.block, base_address);
- #else
- {
- struct block * bl = sym->value.block;
- #ifdef DEBUG0
- if(atari_debug)
- {
- fprintf_filtered(stderr, " start %X->%X\n",
- BLOCK_START(bl), BLOCK_START(bl) + base_address);
- }
- #endif
- /* BLOCK_START(bl) += base_address; */
- #ifdef DEBUG0
- if(atari_debug)
- {
- fprintf_filtered(stderr, " end %X->%X\n",
- BLOCK_END(bl), BLOCK_END(bl) + base_address);
- }
- #endif
- /* BLOCK_END(bl) += base_address; */
- }
- #endif
- #ifdef DEBUG
- if(atari_debug)
- {
- fprintf_filtered(stderr, " ...end block\n");
- }
- #endif
- }
- else
- {
- #ifdef DEBUG
- if(atari_debug)
- {
- fprintf_filtered(stderr, " is not relocatable: (%s, %s)\n",
- d_namespace[sym->namespace], d_aclass[sym->class]);
- }
- #endif
- }
- }
- }
- }
-